using System;
using System.Collections;
using System.Globalization;
using System.Security.Principal;
using System.Threading;
using System.Web;
using Sedna.Core;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Common;
using Sedna.Core.DataBinding;
using Sedna.Core.Security;
using log4net;

namespace Sedna.UI.Access.Actions
{
	/// <summary>
	/// This action calls the underlying authenticator
	/// and injects a successfully logged in principal
	/// 
	/// If the action cannot login a User a <see cref="LoginException"/>
	/// is thrown, in which case the special <see cref="LoginExceptionHandler"/>
	/// is usually configured to redirect a User to login page once again
	/// 
	/// The action takes an instance of filled in User class from the "ec['loginUser']" in ExecutionContext.
	/// The latter, however, can be altered by setting up the <see cref="LoginAuthenticateAction.BindingPath"/> property
	/// 
	/// TODO: handle culture selection
	/// </summary>
	public class LoginAuthenticateAction : AbstractAction
	{

		private IAuthenticator authenticator;
		private IPrincipalInjector principalInjector;
		private string bindingPath = "ec['loginUser']";
        private string passwordExpireStatus;
        private string loginPath;
        private string passwordPath;

		private ILog log = LogManager.GetLogger(typeof(LoginAuthenticateAction));

		public IAuthenticator Authenticator
		{
			set { authenticator = value; }
		}

		public IPrincipalInjector PrincipalInjector
		{
			set { principalInjector = value; }
		}

		public string BindingPath
		{
			set { bindingPath = value; }
		}

	    public string PasswordExpireStatus
	    {
	        set { passwordExpireStatus = value; }
	    }
	    
	    public string LoginPath
	    {
	        get { return loginPath;}
	        set { loginPath = value;}
	    }
	    
	    public string PasswordPath
	    {
	        get { return passwordPath;}
	        set { passwordPath = value;}
	    }

	    public override IActionResult Execute(IExecutionContext executionContext)
		{
			string username = executionContext.GetPropertyValue(loginPath) as string;
			string password = executionContext.GetPropertyValue(passwordPath) as string;


			if(username == null || username == string.Empty)
			{
				log.Debug("invalid username, it must not be empty or null");
				throw new LoginException("invalid username, it must not be empty or null");
			}

			if(password == null)
			{
				log.Debug("invalid password, it must not be null");
				throw new LoginException("invalid password, it must not be null");
			}


			IPrincipal principal = null;

			try
			{
				principal = authenticator.Authenticate(username, password);
			}
			catch (Exception e)
			{
				throw new LoginException("error while trying to authenticate", e);
			}
			if(principal == null)
			{
                scopePathParser.Parse("ec['errorName']").Value = "authentication failed";
			    throw new LoginException("authentication failed");
			}
		    
			Thread.CurrentPrincipal = principal;
			HttpContext.Current.User = principal;
			CultureInfo currentCulture = ParseCulture(executionContext);
			Thread.CurrentThread.CurrentCulture = currentCulture;
			Thread.CurrentThread.CurrentUICulture = currentCulture;
	        
		    UserMapper.StoreCurrentState();
		    
            principalInjector.AfterRequest(HttpContext.Current);		   

	        /*if(((SednaWorkPrincipal)principal).User.PasswordExpires<DateTime.Now)
	        {
	            scopePathParser.Parse("ec['changePasswordMode']").Value = true;
                scopePathParser.Parse("ec['loginMode']").Value = false;
	            return CreateResult(passwordExpireStatus);
	        }*/
	        
			return CreateResult(successStatus);
		}

		private CultureInfo ParseCulture(IExecutionContext executionContext)
		{
			string language = null;

			object Value = executionContext.GetPropertyValue("ec['SelectedUILanguageValue']");

			if (Value != null)
			{
				if (Value is DataBinder.TranslatorValueWrapper)
					language = ((DataBinder.TranslatorValueWrapper)Value).GetValue(null).ToString();
				else
					language = Value as string;
			}


            if (language == null || language == string.Empty || language.ToLower() == "neutral" || language.ToLower() == "default")
			{
				return CultureInfo.InvariantCulture;
                //return (principalWrapper != null) ? principalWrapper.DefinedCulture : CultureInfo.InvariantCulture;				
			}
			
			switch (language.ToLower())
			{
                case "en-US":
                    {
                        return CultureInfo.InvariantCulture;
                    }
				case "ru-RU":
					{
						return CultureInfo.CreateSpecificCulture(language);
					}
				default:
					{
						try
						{
							return CultureInfo.CreateSpecificCulture(language);
						}
						catch(Exception e)
						{
							log.Debug(e.Message);

							return CultureInfo.InvariantCulture;
						}
					}
			}

//			return CultureInfo.CreateSpecificCulture(language);
		}
	}
}
